package com.lovezy.platform.wiki.service.impl;

import com.github.pagehelper.PageInfo;
import com.lovezy.platform.core.base.enums.StatusEnum;
import com.lovezy.platform.core.base.enums.TrueOrFalseEnum;
import com.lovezy.platform.core.base.query.SortTypeEnum;
import com.lovezy.platform.core.exception.ResourceNotFoundException;
import com.lovezy.platform.core.utils.ObjectUtil;
import com.lovezy.platform.core.valid.ValidatorUtil;
import com.lovezy.platform.filestore.service.FileHelper;
import com.lovezy.platform.wiki.enums.TraitTypeEnum;
import com.lovezy.platform.wiki.enums.WikiSortTypeEnum;
import com.lovezy.platform.wiki.exception.WikiExceptionEnum;
import com.lovezy.platform.wiki.form.FollowForm;
import com.lovezy.platform.wiki.form.GameInfoForm;
import com.lovezy.platform.wiki.model.Game;
import com.lovezy.platform.wiki.model.GameExtend;
import com.lovezy.platform.wiki.model.GameName;
import com.lovezy.platform.wiki.model.GameTrait;
import com.lovezy.platform.wiki.query.WikiQuery;
import com.lovezy.platform.wiki.service.GameExtendService;
import com.lovezy.platform.wiki.service.GameFollowService;
import com.lovezy.platform.wiki.service.GameNameService;
import com.lovezy.platform.wiki.service.GameService;
import com.lovezy.platform.wiki.service.GameTraitService;
import com.lovezy.platform.wiki.service.WikiService;
import com.lovezy.platform.wiki.vo.WikiTraitVo;
import com.lovezy.platform.wiki.vo.WikiVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.lovezy.platform.core.utils.ObjectUtil.copy;
import static com.lovezy.platform.core.utils.ObjectUtil.nonNull;
import static com.lovezy.platform.wiki.exception.WikiExceptionEnum.errorSupplier;
import static com.lovezy.platform.wiki.form.GameInfoFormManager.toGame;
import static com.lovezy.platform.wiki.service.impl.GameRuleServiceImpl.ruleUrl;
import static java.util.stream.Collectors.partitioningBy;
import static java.util.stream.Collectors.toList;

/**
 * Created by jin on 2017/11/4.
 */
@Service
public class WikiServiceImpl implements WikiService{

    @Autowired
    private GameService gameService;

    @Autowired
    private GameTraitService gameTraitService;

    @Autowired
    private GameExtendService gameExtendService;

    @Autowired
    private GameNameService gameNameService;

    @Autowired
    private FileHelper fileHelper;

    @Autowired
    GameFollowService gameFollowService;

    @Override
    @Transactional
    public Game saveWiki(GameInfoForm form) {
        ValidatorUtil.validate(form);
        Game game = gameService.insertGame(form);
        List<GameTrait> traits = gameTraitService.saveGameTrait(form);
        gameExtendService.saveGameExtend(game.getId(),traits);
        gameNameService.saveGameName(game, form.getAlternateNames());
        return game;
    }

    @Override
    public WikiVo findWikiById(Integer gameId) {
        return findWikiById(gameId, null);
    }

    @Override
    public WikiVo findWikiById(Integer gameId,String mid) {
        Game game = gameService.selectById(gameId);
        if (game == null) {
            throw new ResourceNotFoundException(() -> errorSupplier(WikiExceptionEnum.WIKI_NOT_FOUND_EXCEPTION));
        }
        gameService.incrementHit(game.getId(), 1);
        WikiVo wikiVo = new WikiVo();
        copy(game, wikiVo);
        String logoUrl = fileHelper.toDownloadUrl(wikiVo.getLogo());
        wikiVo.setLogo(logoUrl);
        assembleWiki(wikiVo, mid);
        return wikiVo;
    }

    @Override
    public void updateWiki(GameInfoForm form) {
        Game game = toGame(form);
        game.setGmtModify(new Date());
        gameService.updateGame(game);
    }

    @Override
    public PageInfo<WikiVo> findWikiList(WikiQuery query) {
        return gameService.selectList(query);
    }

    @Override
    public PageInfo<WikiVo> findNewList(WikiQuery query) {
        query.setWikiSort(WikiSortTypeEnum.gmtCreate);
        query.setSortType(SortTypeEnum.DESC.getType());
        return gameService.selectList(query);
    }

    @Override
    public void deleteWiki(WikiQuery query) {
        Integer gameId = query.getGameId();
        nonNull(gameId);
        Game game = new Game();
        game.setId(gameId);
        game.setStatus(StatusEnum.DELETED.value());
        game.setGmtModify(new Date());
        gameService.updateGame(game);
    }

    public void followWiki(FollowForm followForm) {

    }

    private void assembleWiki(WikiVo wikiVo,String mid) {
        Integer gameId = wikiVo.getId();

        List<GameName> gameNames = gameNameService.findGameNames(gameId, TrueOrFalseEnum.TRUE.value());
        List<String> names = gameNames.stream().map(GameName::getName).collect(toList());
        wikiVo.setAlternateNames(names);

        List<GameExtend> gameExtends = gameExtendService.findGameExtends(gameId);
        Map<Boolean, List<WikiTraitVo>> traitMap = gameExtends.stream().map(extend -> gameTraitService.selectById(extend.getTraitId()))
                .filter(Objects::nonNull)
                .map(trait -> ObjectUtil.copyTo(trait, new WikiTraitVo()))
                .collect(partitioningBy(trait -> trait.getType() == TraitTypeEnum.CATEGORIE.value()));
        wikiVo.setCategories(traitMap.get(Boolean.TRUE));
        wikiVo.setMechanisms(traitMap.get(Boolean.FALSE));

        if (mid != null) {
            FollowForm followForm = new FollowForm();
            followForm.setMemberId(mid);
            followForm.setId(gameId);
            boolean followed = gameFollowService.isFollowed(followForm);
            wikiVo.setHasFollow(followed ? TrueOrFalseEnum.TRUE.value() : TrueOrFalseEnum.FALSE.value());
        }

        Map<String, String> ruleUrls = ruleUrl(gameId);
        if (ruleUrls != null) {
            wikiVo.setPdf(ruleUrls.get("pdf"));
            wikiVo.setViewUrl(ruleUrls.get("viewUrl"));
        }
    }

}
